﻿using System;
using System.Collections.Generic;
using Citi.Scheduler.Domain;
using System.ComponentModel;

namespace Citi.Scheduler.WebUi.Models
{
    public class RoutineExecutionModel : ModelBase<RoutineExecutionModel, RoutineExecution>
    {
        public DateTime? StartsOn { get; set; }
        public DateTime? EndsOn { get; set; }
        public DateTime ScheduledDateTime { get; set; }
        public int? MachineId { get; set; }
        public int RoutineId { get; set; }
        public short Tentatives { get; set; }
        public RoutineExecutionHistoryModel LastHistory { get; set; }
        public TimeSpan? CustomerSLA { get; set; }

        public List<RoutineExecutionHistoryModel> RoutineExecutionHistories { get; set; }
        public List<RoutineErrorModel> RoutineErrors { get; set; }
        public RoutineModel Routine { get; set; }
        public MachineModel Machine { get; set; }

        public enum ExecutionStatus
        {
            [Description("Executed On Time")]
            ExecutedOnTime,
            [Description("Not Executed")]
            NotExecuted,
            Error,
            [Description("Executed Late")]
            ExecutedLate,
            Scheduled,
            Canceled,
            [Description("Waiting to Execute")]
            WaitingToExecute,
            [Description("In Progress")]
            InProgress
        }

        //public RoutineExecutionStatus Status { get; set; }

        public ExecutionStatus Status
        {
            get
            {
                var lastStatus = RoutineExecutionHistories[0].Status;

                if (lastStatus == RoutineExecutionStatus.Scheduled)
                    return ExecutionStatus.Scheduled;

                if (lastStatus == RoutineExecutionStatus.Error || lastStatus == RoutineExecutionStatus.ExecutedWithError)
                    return ExecutionStatus.Error;

                if (lastStatus == RoutineExecutionStatus.Canceled || lastStatus == RoutineExecutionStatus.CanceledAfterWaiting)
                    return ExecutionStatus.Canceled;

                if (lastStatus == RoutineExecutionStatus.PredecessorNotScheduled || lastStatus == RoutineExecutionStatus.PredecessorRoutineWithError)
                    return ExecutionStatus.NotExecuted;

                var deadLine = CustomerSLA.HasValue
                    ? ScheduledDateTime.Date.Add(CustomerSLA.Value)
                    : ScheduledDateTime.AddMinutes((Routine.EstimatedTime + Routine.EstimatedTime * Routine.PercentageAcceptableVariation / 100) + 5);

                if (DateTime.Now <= deadLine && lastStatus == RoutineExecutionStatus.InProgress)
                    return ExecutionStatus.InProgress;

                if (DateTime.Now > deadLine && lastStatus == RoutineExecutionStatus.InProgress)
                    return ExecutionStatus.Error;

                if (lastStatus == RoutineExecutionStatus.Executed && EndsOn <= deadLine)
                    return ExecutionStatus.ExecutedOnTime;  

                if (lastStatus == RoutineExecutionStatus.Executed && EndsOn > deadLine)
                    return ExecutionStatus.ExecutedLate;

                if (DateTime.Now <= deadLine && (lastStatus == RoutineExecutionStatus.WaitingFreeMachine || lastStatus == RoutineExecutionStatus.WaitingPredecessorRoutine
                    || lastStatus == RoutineExecutionStatus.WaitingSpecificFreeMachine))
                    return ExecutionStatus.WaitingToExecute;

                if (DateTime.Now > deadLine && (lastStatus == RoutineExecutionStatus.WaitingFreeMachine || lastStatus == RoutineExecutionStatus.WaitingPredecessorRoutine
                    || lastStatus == RoutineExecutionStatus.WaitingSpecificFreeMachine))
                    return ExecutionStatus.NotExecuted;

                return ExecutionStatus.NotExecuted;
            }
        }
    }
}